package com.seres.backend.admin;

import java.util.ArrayList;
import java.util.List;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;

public class ScenariosAndAnswersParser {
	private static final int MODULE_ID_COL_NR = 1;
	private static final int SCENARIO_ID_COL_NR = 2;
	private static final int DESCRIPTION_COL_NR = 3;
	private static final int IMAGE_NAME_DESCRIPTION_COL_NR = 4;
	private static final int QUESTION_COL_NR = 5;
	private static final int IMAGE_NAME_QUESTION_COL_NR = 6;
	private static final int ANSWER_COL_NR = 7;	
	private static final int NEXT_SCENARIO_ID_COL_NR = 8;
	private static final int RISK_IMPACT_COL_NR = 9;
	private static final int STAKEHOLDER_ID_IMPACT_COL_NR = 11;	
	private static final int IMPACT_SCORE_COL_NR = 11;
	private static final int AI_INPUT_COL_NR = 11;
	
	private static final int Q_AND_A_BLOCK_LENGTH = 11;
	
	private static final int TITLE_COL_NR = 1;
	private static final int TITLE_ROW_NR = 1;
	private static final String TITLE = "scenarios & answers";
	
	private static final int DATA_START_ROW_NR = 2;
	
	private boolean dataEndReached = false;
	
	private XSSFSheet worksheet;
	private List<Integer> allowedStakeholderIds;
	
	public ScenariosAndAnswersParser(XSSFSheet worksheet, List<Integer> allowedStakeholderIds){
		setWorksheet(worksheet);
		setAllowedStakeholderIds(allowedStakeholderIds);
	}
	public ScenariosAndAnswersParserResult parse(){
		
		ScenariosAndAnswersParserResult result = new ScenariosAndAnswersParserResult();
		
		for(int i = 0; !isDataEndReached(); i++){
			System.out.println("isDataEndReached: " + isDataEndReached());
			boolean reachedBlockEnd = false;
			
			List<Integer> stakeholderIDs = null;
			List<Integer> impactScores = null;
			List<String> aiInput = null;
			String question;
			String questionImage;
			String answer = "";
			int nextScenarioId = 0;
			int riskImpact = 0;
			int scenarioId;
			int moduleId;
			ScenarioBlock scenarioBlock = new ScenarioBlock();
			boolean containsData = false;
			
			for(int j = 0; j < Q_AND_A_BLOCK_LENGTH && !reachedBlockEnd && !isDataEndReached(); j++){
				XSSFRow row = getWorksheet().getRow(DATA_START_ROW_NR + (i*(Q_AND_A_BLOCK_LENGTH)) + j);
				XSSFRow nextRow = getWorksheet().getRow(DATA_START_ROW_NR + (i*(Q_AND_A_BLOCK_LENGTH)) + j + 1);
				
				if(j == 0){
					stakeholderIDs = parseStakeholderIDs(row);
					
//					//print list
//					System.out.println("*** stakeholder ids block " + i + " ***");
//					for(int k = 0; k < stakeholderIDs.size(); k++){
//						System.out.println("ID: " + stakeholderIDs.get(k));
//					}
//					System.out.println("*** end stakeholder ids list ***");
				}
				else if(j == 1){
					System.out.println("containsData(row.getCell(MODULE_ID_COL_NR)): " + containsData(row.getCell(MODULE_ID_COL_NR)));
					System.out.println("containsData(row.getCell(QUESTION_ID_COL_NR)): " + containsData(row.getCell(SCENARIO_ID_COL_NR)));
					if(containsData(row.getCell(MODULE_ID_COL_NR)) && containsData(row.getCell(SCENARIO_ID_COL_NR))){ //contains module id && contains question id
						containsData = true;
						
						moduleId = parseModuleId(row.getCell(MODULE_ID_COL_NR));
						scenarioId = parseScenarioId(row.getCell(SCENARIO_ID_COL_NR));
						scenarioBlock.setModuleId(moduleId);
						scenarioBlock.setScenarioId(scenarioId);
						
						if(containsData(row.getCell(DESCRIPTION_COL_NR))){ //contains description
							String description = parseDescription(row.getCell(DESCRIPTION_COL_NR));
							String descriptionImage = parseDescriptionImage(row.getCell(IMAGE_NAME_DESCRIPTION_COL_NR));
//							descriptions.add(description);
//							descriptionImages.add(descriptionImage);
							scenarioBlock.addDescription(description);
							scenarioBlock.addImageName(descriptionImage);
						}
						
						if(containsData(row.getCell(QUESTION_COL_NR))){ //contains question
							question = parseQuestion(row.getCell(QUESTION_COL_NR));
							questionImage = parseQuestionImage(row.getCell(IMAGE_NAME_QUESTION_COL_NR));		
							
							System.out.println("question: " + question);
							System.out.println("question image: " + questionImage);
							
							scenarioBlock.setQuestion(question);
							scenarioBlock.setQuestionImageName(questionImage);
						}

						
						if(containsData(row.getCell(ANSWER_COL_NR))){ //contains answer
							answer = parseAnswer(row.getCell(ANSWER_COL_NR));
//							answers.add(answer);
							nextScenarioId = 0;
							if(containsData(row.getCell(NEXT_SCENARIO_ID_COL_NR))){
								nextScenarioId = parseNextScenarioId(row.getCell(NEXT_SCENARIO_ID_COL_NR));
							}
//							nextScenarioIds.add(nextScenarioId);
							riskImpact = parseImpact(row.getCell(RISK_IMPACT_COL_NR));
							aiInput = parseAiInputs(row);
							impactScores = parseImpactScores(nextRow);
							
							scenarioBlock.addAnswerLine(new AnswerLine(answer, nextScenarioId, riskImpact, stakeholderIDs, impactScores, aiInput));
						}
						reachedBlockEnd = isBlockEndReached(row);
					}
					else{
						setDataEndReached(true);
						System.out.println("setDataEndReached");
//						break;
					}
				}
				else{ // not first or second line
					if(j % 2 == 1){
						if(containsData(row.getCell(DESCRIPTION_COL_NR))){ //contains description
							String description = parseDescription(row.getCell(DESCRIPTION_COL_NR));
							String descriptionImage = parseDescriptionImage(row.getCell(IMAGE_NAME_DESCRIPTION_COL_NR));
//							descriptions.add(description);
//							descriptionImages.add(descriptionImage);
							scenarioBlock.addDescription(description);
							scenarioBlock.addImageName(descriptionImage);
						}
						if(containsData(row.getCell(ANSWER_COL_NR))){ //contains answer
							answer = parseAnswer(row.getCell(ANSWER_COL_NR));
//							answers.add(answer);
							nextScenarioId = 0;
							if(containsData(row.getCell(NEXT_SCENARIO_ID_COL_NR))){
								nextScenarioId = parseNextScenarioId(row.getCell(NEXT_SCENARIO_ID_COL_NR));
							}
//							nextScenarioIds.add(nextScenarioId);
							riskImpact = parseImpact(row.getCell(RISK_IMPACT_COL_NR));
							aiInput = parseAiInputs(row);
							impactScores = parseImpactScores(nextRow);
							
							scenarioBlock.addAnswerLine(new AnswerLine(answer, nextScenarioId, riskImpact, stakeholderIDs, impactScores, aiInput));
							
						}
						reachedBlockEnd = isBlockEndReached(row);
					}
						
						

				}
							
			}

			
//			//print answers
//			System.out.println("*** answers block " + i + " ***");
//			for(int k = 0; k < answers.size(); k++){
//				System.out.println("answer: " + answers.get(k));
//			}
//			System.out.println("*** end answers list ***");
//
//			//print descriptions
//			System.out.println("*** descriptions block " + i + " ***");
//			for(int k = 0; k < descriptions.size(); k++){
//				System.out.println("description: " + descriptions.get(k));
//			}
//			System.out.println("*** end descriptions list ***");
			
			if(containsData){
				result.addScenarioBlock(scenarioBlock);				
			}

		}
		return result;
	}
	private List<String> parseAiInputs(XSSFRow row) {
		List<String> aiInput = new ArrayList<String>();
		boolean aiInputEndReached = false;
		int i = 0;
		while(!aiInputEndReached){
			if(containsData(row.getCell(AI_INPUT_COL_NR + i))){ // contains AI input
				aiInput.add(parseAiInput(row.getCell(AI_INPUT_COL_NR + i)));
			}
			else{
				aiInputEndReached = true;
			}
			i++;
		}
		return aiInput;
	}
	private boolean isBlockEndReached(XSSFRow row){
		return !containsData(row.getCell(ANSWER_COL_NR)) && !containsData(row.getCell(DESCRIPTION_COL_NR)); //if does not contain answer and does not contain description	}
	}
	private List<Integer> parseStakeholderIDs(XSSFRow row) {
		List<Integer> stakeholderIds = new ArrayList<Integer>();
		boolean stakeholderIDsEndReached = false;
		int i = 0;
		while(!stakeholderIDsEndReached){
			if(containsData(row.getCell(STAKEHOLDER_ID_IMPACT_COL_NR + i))){ // contains stakeholder id
				stakeholderIds.add(parseStakeholderId(row.getCell(STAKEHOLDER_ID_IMPACT_COL_NR + i)));
			}
			else{
				stakeholderIDsEndReached = true;
			}
			i++;
		}
		return stakeholderIds;
	}
	private List<Integer> parseImpactScores(XSSFRow row) {
		List<Integer> impactScores = new ArrayList<Integer>();
		boolean impactScoresEndReached = false;
		int i = 0;
		while(!impactScoresEndReached){
			if(containsData(row.getCell(IMPACT_SCORE_COL_NR + i))){ // contains impact score
				impactScores.add(parseImpact(row.getCell(IMPACT_SCORE_COL_NR + i)));
			}
			else{
				impactScoresEndReached = true;
			}
			i++;
		}
		return impactScores;
	}

	private String parseDescription(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_STRING){
			return cell.getStringCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid description cell");
		}
	}
	private String parseAiInput(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_STRING){
			return cell.getStringCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid ai input cell");
		}
	}
	private String parseDescriptionImage(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_STRING){
			return cell.getStringCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid description image cell");
		}
	}
	private String parseQuestion(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_STRING){
			return cell.getStringCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid question cell");
		}
	}
	private String parseQuestionImage(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_STRING){
			return cell.getStringCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid question image cell");
		}
	}
	private String parseAnswer(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_STRING){
			return cell.getStringCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid answer cell");
		}
	}
	
	private int parseNextScenarioId(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid next scenario id cell");
		}
	}
	private int parseScenarioId(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid scenario id cell");
		}
	}
	private int parseModuleId(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid module id cell");
		}
	}
	private int parseImpact(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid impact cell");
		}
	}	
	private int parseStakeholderId(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC && canHaveAsStakeholderId((int) cell.getNumericCellValue())){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid stakeholder id cell");
		}
	}
	private boolean canHaveAsStakeholderId(int numericCellValue) {
		return getAllowedStakeholderIds().contains(numericCellValue);
	}
	private boolean containsData(XSSFCell cell){
		return cell.getCellType() != Cell.CELL_TYPE_BLANK;
	}
	private boolean isDataEndReached() {
		return dataEndReached;
	}
	private void setDataEndReached(boolean dataEndReached) {
		this.dataEndReached = dataEndReached;
	}
	private XSSFSheet getWorksheet() {
		return worksheet;
	}
	public boolean canHaveAsWorksheet(XSSFSheet worksheet){
		return worksheet.getRow(TITLE_ROW_NR).getCell(TITLE_COL_NR).getStringCellValue().toLowerCase().equals(TITLE);
	}
	public boolean canHaveAsModuleType(List<String> allowedModuleTypes, String type){
		for(String allowedModuleType : allowedModuleTypes){
			if(allowedModuleType.equals(type)){
				return true;
			}
		}
		return false;
	}
	private void setWorksheet(XSSFSheet worksheet) {
		if(canHaveAsWorksheet(worksheet)){
			this.worksheet = worksheet;
		}
		else{
			throw new IllegalArgumentException("invalid modules worksheet");
		}
		
	}
	private void setAllowedStakeholderIds(List<Integer> allowedStakeholderIds) {
		this.allowedStakeholderIds = allowedStakeholderIds;
	}
	public List<Integer> getAllowedStakeholderIds() {
		return allowedStakeholderIds;
	}
}
